package com.zhekou.dao;


import com.zhekou.db.Db;
import com.zhekou.util.JdbcPage;
import com.zhekou.util.ReflectionUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.persistence.Id;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * User: chjp
 * Date: 12-3-5
 * Time: 上午11:09
 */
public abstract class BaseDAO<T> {
    @Autowired
    private Db db;
    protected Class<T> entityClass;
    private String cache_key;
    private String id_name;
    /* @Autowired
  private HiMemCacheClient hiMemCacheClient;*/


    public BaseDAO() {
        this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass());
//        if (this.entityClass.getAnnotation(Cacheable.class) != null) {
        cache_key = entityClass.getSimpleName().toLowerCase() + "_";
        id_name = ReflectionUtils.getAnnotatedFieldName(entityClass, Id.class);
//        }

    }

    public void setDb(final Db db) {
        this.db = db;
    }

    public Serializable create(final T entity) {
        try {
            Serializable id = db.create(entity);
            String name = ReflectionUtils.getAnnotatedFieldName(entityClass, Id.class);
            BeanUtils.setProperty(entity, name, id);
            /* if (cache_key != null) {
                hiMemCacheClient.put(cache_key + id, entity);
            }*/
            return id;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public T get(final Serializable id) {
        T o = null;
        /* if (cache_key != null) {
          o = (T) hiMemCacheClient.get(cache_key + id);
      }
      if (o != null) {
          return o;
      } else {*/
        o = db.getById(entityClass, id);
        /* if (cache_key != null && o != null) {
            hiMemCacheClient.put(cache_key + id, o);
        }*/
        return o;
//        }
    }

    public void delete(final T entity) {
        db.deleteEntity(entity);
       /* if (cache_key != null) {
            Object id = ReflectionUtils.getFieldValue(entity, id_name);
            hiMemCacheClient.remove(cache_key + id);
        }*/
    }

    public void deleteById(final Serializable id) {
        db.deleteById(entityClass, id);
        /*if (cache_key != null) {
            hiMemCacheClient.remove(cache_key + id);
        }*/
    }

    public void update(T entity) {
        db.updateEntity(entity);
       /* if (cache_key != null) {
            Object id = ReflectionUtils.getFieldValue(entity, id_name);
            hiMemCacheClient.put(cache_key + id, entity);
        }*/
    }

    public List<T> doQueryLimitList(String sql, int limits, int cacheMinuts, Object... params) {
        return db.queryForLimitedList(entityClass.getSimpleName(), sql, 0, limits, params);
    }


    public List<T> doQueryList(String sql, int cacheMinuts, Object... params) {
        return db.queryForList(entityClass.getSimpleName(), sql, params);
    }

    public JdbcPage<T> doQueryPage(String sql, int curPage, int pageSize, int cacheLimits, Object... params) {
        if (pageSize < 0) {
            List<T> list = doQueryList(sql, cacheLimits, params);
            return new JdbcPage<T>(list, -1, curPage, pageSize);
        } else {
            if (curPage < 1) {
                curPage = 1;
            }
            int firstResult = (curPage - 1) * pageSize;
            List<T> objects = db.queryForLimitedList(entityClass.getSimpleName(), sql, firstResult, pageSize, params);
            String countSql = "select count(*) " + removeSelect(removeOrders(sql));
            long total = db.queryForLong(countSql, params);
            return new JdbcPage<T>(objects, total, curPage, pageSize);
        }
    }

    public long doQueryCount(String sql, int cacheMinuts, Object... params) {
        return db.queryForLong(sql, params);
    }

    public T doQueryFirst(String sql, int cacheMinuts, Object... params) {
        return (T) db.queryForObject(entityClass.getSimpleName(), sql, params);
    }

    public List<Map<String, Object>> queryForList(String sql, Object... params) {
        return db.queryForList(sql, params);
    }

    private String removeSelect(String hql) {
        int beginPos = hql.toLowerCase().indexOf("from");
        return hql.substring(beginPos);
    }

    /*
     * 去除orderby 子句
     */
    private String removeOrders(String hql) {
        Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(hql);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "");
        }
        m.appendTail(sb);
        return sb.toString();
    }
}
